package com.fjl.controller;

import com.fjl.client.config.MySqlMemory;
import org.apache.commons.lang3.StringUtils;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.memory.ChatMemoryRepository;
import org.springframework.ai.chat.messages.AssistantMessage;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class AssistantController {
    @Autowired
    private ChatMemoryRepository chatMemoryRepository;

    @Autowired
    private ChatModel chatModel;

    @Autowired
    private ChatClient chatClient;
    /**
     * 会话聊天
     */
    @RequestMapping("/session/chat")
    public String sessionChat(@RequestParam("conversionId") String conversionId,
                              @RequestParam("msg") String msg){
        /**
         * conversionId 会话ID，ID相同则视为是同一个会话的内容
         */
        // 先通过 conversionId 来获取当前会话的所有消息
        List<Message> messages = chatMemoryRepository.findByConversationId(conversionId);
        if(CollectionUtils.isEmpty(messages)){
            messages = new ArrayList<>();
        }
        // 构建用户消息
        UserMessage userMessage = UserMessage.builder().text(msg).build();
        // 将用户消息也放入 messages
        messages.add(userMessage);
        // 将所有的消息都提交给大模型
        Prompt prompt = Prompt.builder().messages(messages).build();
        String content = chatClient.prompt(prompt).call().content();
        if(StringUtils.isNotBlank(content)){
            AssistantMessage assistantMessage = new AssistantMessage(content);
            // 将大模型回复的消息写入 messages
            messages.add(assistantMessage);
            // 将当前会话的所有消息全部保存（覆盖式保存）
            chatMemoryRepository.saveAll(conversionId, messages);
        }
        return content;
    }


    @Autowired
    private MySqlMemory mySqlMemory;
    /**
     * 记忆聊天
     */
    @RequestMapping("/memory/chat")
    public Flux<String> memoryChat(@RequestParam(name = "conversionId", required = false, defaultValue = "1") String conversionId,
                                   @RequestParam(name = "msg", required = true) String msg){
        // 定义记忆功能的增强器
        MessageChatMemoryAdvisor chatMemoryAdvisor = MessageChatMemoryAdvisor.builder(mySqlMemory)
                .conversationId(conversionId)
                .build();
        return chatClient.prompt()
                .user(msg)
                .advisors(chatMemoryAdvisor) // 引入记忆增强器
                .stream().content();
    }
    /*
    PromptTemplate 是提示词模版，使用它可以实现内容的动态替换，并保证输出结果的一致性，具体优点如下：
        动态内容管理：通过占位符（如 {变量名}）将固定模版与动态输入解耦，避免重复编写相似提示词。
        输出质量可控：模版可嵌入约束条件（如“用JSON格式回复”），减少模型生成内容的随机性，确保输出符合业务规范。
        开发效率优化：避免硬编码提示词，通过模版统一管理提逻辑，降低维护成本，尤其在需要频繁提示策略的场景中优势显著。
    */
    @RequestMapping("/template/chat")
    public String templateChat(@RequestParam(name = "msg", required = true)  String msg){
        PromptTemplate promptTemplate = new PromptTemplate("讲一个关于{topic}的故事");
        HashMap hashMap = new HashMap();
        hashMap.put("topic", msg);
        Prompt prompt = promptTemplate.create(hashMap);
        return chatClient.prompt(prompt).call().content();
    }
}
